package com.fla.puzzle.ui;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.danikula.aibolit.Aibolit;
import com.danikula.aibolit.annotation.InjectOnClickListener;
import com.danikula.aibolit.annotation.InjectOnItemClickListener;
import com.danikula.aibolit.annotation.InjectService;
import com.danikula.aibolit.annotation.InjectView;
import com.fla.puzzle.PackDataProvider;
import com.fla.puzzle.PuzzleApplication;
import com.fla.puzzle.R;
import com.fla.puzzle.pack.PackItem;
import com.fla.puzzle.utils.AndroidUtils;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Shows 'Options' screen
 */
public class OptionsActivity extends BaseActivity {
    public static final int BACK_TO_PUZZLES = RESULT_FIRST_USER;
    public static final int PLAY_NEXT = RESULT_FIRST_USER + 1;
    public static final int RESHUFFLE = RESULT_FIRST_USER + 2;
    public static final int CHANGE_COMPLEXITY = RESULT_FIRST_USER + 3;

    private static final String ENABLE_LOAD_NEXT_KEY = OptionsActivity.class.getName() + "ENABLE_LOAD_NEXT_KEY";
    private static final String PACK_ITEM_KEY = OptionsActivity.class.getName() + "PACK_ITEM_KEY";
    private static final String IS_OPTIONS_KEY = OptionsActivity.class.getName() + "IS_OPTIONS_KEY";
    
    @InjectService
    private PuzzleApplication application;

    @InjectService
    private PackDataProvider packDataProvider;

    @InjectView(R.id.headerTextView)
    private TextView headerTextView;

    @InjectView(android.R.id.list)
    private ListView list;

    private OptionsAdapter optionsAdapter;

    private boolean isOptions;
    private PackItem packItem;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        isOptions = getIntent().getBooleanExtra(IS_OPTIONS_KEY, true);
        boolean enableLoadNext = getIntent().getBooleanExtra(ENABLE_LOAD_NEXT_KEY, false);
        packItem = (PackItem) getIntent().getSerializableExtra(PACK_ITEM_KEY);

        Aibolit.setInjectedContentView(this, R.layout.options_activity);

        List<String> options = new ArrayList<String>();
        options.addAll(Arrays.asList(getFirstOptions()));
        options.addAll(Arrays.asList(getResources().getStringArray(R.array.common_options)));

        list.setAdapter(optionsAdapter = new OptionsAdapter(this, R.layout.options_item, options));

        if (!enableLoadNext) {
            optionsAdapter.addDisabledPosition(getFirstOptions().length);
        }

        headerTextView.setText(isOptions ? R.string.options : R.string.finished);
    }

    private String[] getFirstOptions() {
        return getResources().getStringArray(isOptions ? R.array.game_options : R.array.finish_options);
    }

    @InjectOnItemClickListener(android.R.id.list)
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        boolean handled = isOptions ? handleGameOptions(position) : handleFinishOptions(position);

        if (handled) {
            return;
        }

        // handle common options
        int otherOptionsCount = getFirstOptions().length;
        switch (position - otherOptionsCount) {
            case 0:
                // play next
                setResult(PLAY_NEXT);
                finish();
                break;
            case 1:
                // Back to the Puzzles List
                setResult(BACK_TO_PUZZLES);
                finish();
                break;
            case 2:
                // Sound options
                new SoundOptionsDialog(this).show();
                break;
            case 3:
                // Get more puzzles free
                AndroidUtils.getMore(this, "com.fla.puzzle");
                break;
            case 4:
                // Rate the App
                AndroidUtils.launchGooglePlay(this);
                break;
        }
    }

    @Override
    public void onBackPressed() {
        if (!isOptions) {
            setResult(BACK_TO_PUZZLES);
        }
        super.onBackPressed();
    }

    public boolean handleGameOptions(int position) {
        switch (position) {
            case 0:
                setResult(RESHUFFLE);
                finish();
                return true;
            case 1:
                setResult(CHANGE_COMPLEXITY);
                finish();
                return true;
            default:
                return false;
        }
    }

    public boolean handleFinishOptions(int position) {
        switch (position) {
            case 0:
                int width = getResources().getDisplayMetrics().widthPixels;
                int height = getResources().getDisplayMetrics().heightPixels;

                String result = MediaStore.Images.Media.insertImage(getContentResolver(),
                    packDataProvider.loadBitmap(packItem.getImageId(), width, height), packItem.getName(),
                    packItem.getDescription());

                Toast.makeText(this, result != null ? R.string.save_photo_success : R.string.save_photo_fail, Toast.LENGTH_LONG)
                    .show();

                if (result != null) {
                    optionsAdapter.addDisabledPosition(0);
                }

                Log.d("test", "Add image result: " + result);
                return true;
            case 1:
                ImageViewerActivity.start(this, packItem);
                return true;
            default:
                return false;
        }
    }

    /**
     * Starts this activity for result
     * 
     * @param activity Activity invoking activity
     * @param enableLoadNext boolean true if load next button should be enabled
     * @param imageId String the id
     * @param requestCode int request code when starting for result
     */
    public static void startForResult(Activity activity, boolean enableLoadNext, PackItem packItem, boolean isOptions,
        int requestCode) {
        Intent intent = new Intent(activity, OptionsActivity.class);
        intent.putExtra(ENABLE_LOAD_NEXT_KEY, enableLoadNext);
        intent.putExtra(PACK_ITEM_KEY, packItem);
        intent.putExtra(IS_OPTIONS_KEY, isOptions);
        activity.startActivityForResult(intent, requestCode);
    }

    private class OptionsAdapter extends ArrayAdapter<String> {
        private List<Integer> disabledPositions;

        public OptionsAdapter(Context context, int textViewResourceId, List<String> objects) {
            super(context, textViewResourceId, objects);
            disabledPositions = new ArrayList<Integer>();
        }

        public void addDisabledPosition(int position) {
            disabledPositions.add(position);
            notifyDataSetChanged();
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = super.getView(position, convertView, parent);
            ((TextView) view).setTextColor(isEnabled(position) ? Color.WHITE : Color.GRAY);
            return view;
        }

        @Override
        public boolean isEnabled(int position) {
            return !disabledPositions.contains(position);
        }
    }

    private class SoundOptionsDialog extends Dialog {
        @InjectView(R.id.enableFinishSound)
        private CheckBox enableFinishSound;

        public SoundOptionsDialog(Context context) {
            super(context);
            setTitle(R.string.sound_options);
            Aibolit.setInjectedContentView(this, R.layout.sound_dialog);

            enableFinishSound.setChecked(application.isSoundEnabled());
        }

        @InjectOnClickListener(R.id.okButton)
        private void onSaveClicked(View view) {
            application.setSoundEnabled(enableFinishSound.isChecked());
            dismiss();
        }

        @InjectOnClickListener(R.id.cancelButton)
        private void onCancelClicked(View view) {
            dismiss();
        }
    }
}
